package com.db.nearcache.remote;

import java.rmi.RemoteException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.db.nearcache.cache.Cache;

public class RemoteCache implements Cache, ObservableRemoteCache {

	private ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();
	private List<RemoteCacheObserver> observers = new CopyOnWriteArrayList<>();
	private Logger logger = Logger.getLogger(RemoteCache.class.getName());

	@Override
	public void put(String key, Object value) {
		if (logger.isLoggable(Level.INFO)) {
			logger.info(String.format("put (%s => %s)%n", key, value));
		}

		cache.put(key, value);
		for (RemoteCacheObserver observer : observers) {
			try {
				observer.update(key, value);
			} catch (RemoteException e) {
				observers.remove(observer);
				if (logger.isLoggable(Level.INFO)) {
					logger.info("observer disconnected");
				}
			}
		}
	}

	@Override
	public Object get(String key) {
		return cache.get(key);
	}

	@Override
	public void subscribe(RemoteCacheObserver observer) {
		observers.add(observer);
	}

	@Override
	public Map<String, Object> snapshot() throws RemoteException {
		return Collections.unmodifiableMap(cache);
	}

}
